// 顶部：仅类型导入 + 拆分 logger 的值/类型导入
import type { ICallbackParams, IHeaders, IParams } from "./request";
import Logger from "../logger";
import type { ILogger } from "../logger";
import { CONTENT_TYPE, ERROR, HEADER, METHOD, RESPONSE_TYPE, TYPE } from "./config";
import utils from "../utils";

// 条件导入 https 模块，仅在 Node.js 环境中可用
let https: any;
try {
    if (typeof process !== 'undefined' && process.versions && process.versions.node) {
        https = require('https');
    }
} catch (e) {
    // 在浏览器环境中忽略
}

/**
 * 发送XMLHttpRequest请求的主函数
 * @param params - 请求参数
 * @param callbackParams - 回调参数（可选）
 * @returns 返回一个Promise，解析为请求结果
 */
const sendXmlHttpRequest = function <T>(params: IParams, callbackParams?: ICallbackParams): Promise<T> {
    callbackParams = callbackParams || {};
    const logger: ILogger = new Logger(TYPE.Xml, params.loggerLevel);

    const headers = prepareRequestHeaders(params.headers);
    const { url, body } = buildRequestUrlAndBody(params, headers);
    logger.debug('url', url);
    logger.debug('headers', headers);
    logger.debug('body', body);

    return executeRequest<T>(params, url, body, headers, callbackParams, logger);
}

/**
 * 准备请求头，确保包含Content-Type
 * @param headers - 原始请求头数组
 * @returns 处理后的请求头数组
 */
function prepareRequestHeaders(headers?: IHeaders[]): IHeaders[] {
    const processedHeaders = utils.to.deepCopyArray(headers ?? []);
    const contentType = processedHeaders.find(m => m.name === HEADER.ContentType);
    if (!contentType) {
        processedHeaders.push({ name: HEADER.ContentType, value: CONTENT_TYPE.ApplicationJson });
    }
    return processedHeaders;
}

/**
 * 根据请求方法和参数构建URL和请求体
 * @param params - 请求参数
 * @param headers - 请求头
 * @returns 包含URL和请求体的对象
 */
function buildRequestUrlAndBody(params: IParams, headers: IHeaders[]) {
    let url: string;
    let body: object | string | undefined;

    if (params.method === METHOD.Get) {
        url = utils.replace.spliceToUrlByJson(params.url, params.requestBody ?? {});
        body = undefined;
    } else {
        url = params.url;
        const contentType = headers.find(m => m.name === HEADER.ContentType) as IHeaders;
        body = processRequestBody(params.requestBody, contentType.value);
    }

    return { url, body };
}

/**
 * 根据Content-Type处理请求体
 * @param body - 原始请求体
 * @param contentType - Content-Type值
 * @returns 处理后的请求体
 */
function processRequestBody(body: object | undefined, contentType: string): object | string | undefined {
    switch (contentType) {
        case CONTENT_TYPE.ApplicationJson:
            return JSON.stringify(body);
        case CONTENT_TYPE.ApplicationWWW:
            return utils.to.jsonToQueryString(body);
        case CONTENT_TYPE.FromData:
            return body;
        default:
            return undefined;
    }
}

/**
 * 执行实际的XMLHttpRequest请求
 * @param params - 请求参数
 * @param url - 请求URL
 * @param body - 请求体
 * @param headers - 请求头
 * @param callbackParams - 回调参数
 * @param logger - 日志记录器
 * @returns 返回一个Promise，解析为请求结果
 */
function executeRequest<T>(
    params: IParams,
    url: string,
    body: object | string | undefined,
    headers: IHeaders[],
    callbackParams: ICallbackParams,
    logger: ILogger
): Promise<T> {
    return new Promise((resolve, reject) => {
        const XmlHttpRequestConstructor = typeof params.request === "undefined" ? XMLHttpRequest : params.request;
        const request = new XmlHttpRequestConstructor();

        // 在 XML 下提示不支持 SSE 解析
        if (params.responseType === 'stream') {
            logger.warn('XMLHttpRequest 不支持 SSE 解析');
            callbackParams?.handleSSEEvent?.({ event: 'error', data: 'XMLHttpRequest adapter does not support SSE', raw: '' });
        }

        // 仅在 Node.js 环境且 https 模块可用时配置 Agent
        if (https && url.startsWith('https://')) {
            const agent = new https.Agent({
                rejectUnauthorized: false
            });
            request.agent = agent;
        }

        // 处理回调
        if (callbackParams?.requestInstance) {
            callbackParams.requestInstance(request);
        }

        // 初始化请求
        request.open(params.method, params.url, params.async);
        headers.forEach(header => request.setRequestHeader(header.name, header.value));
        request.responseType = params.responseType ?? RESPONSE_TYPE.Json;

        let timeoutId: any | number;

        // 请求开始
        request.onloadstart = () => {
            if (params.timeout) {
                timeoutId = setTimeout(() => {
                    logger.info('请求超时');
                    logger.warn('url', url);
                    logger.warn('body', body);
                    request.abort();
                    reject(ERROR.err_408);
                }, params.timeout);
            }
        };

        // 请求结束
        request.onloadend = () => {
            // logger.info('请求结束');
        };

        // 请求超时
        request.ontimeout = () => {
            logger.warn('请求超时');
            reject(ERROR.err_408);
        };

        // 请求被终止
        request.onabort = () => {
            logger.info('请求被终止');
            callbackParams?.handleAbort?.();
        };

        // 请求出错
        // 添加 SSL 错误检测函数
        function getSSLErrorMessage(error: any): string | null {
            if (!error) return null;

            const errorStr = error.toString();
            const errorCode = error.code;

            // 检查各种 SSL 证书错误
            if (errorCode === 'CERT_HAS_EXPIRED' || errorStr.includes('certificate has expired')) {
                return 'SSL证书已过期，请联系服务器管理员更新证书';
            }

            if (errorCode === 'CERT_UNTRUSTED' || errorStr.includes('certificate not trusted')) {
                return 'SSL证书不受信任，请检查证书有效性';
            }

            if (errorCode === 'CERT_INVALID' || errorStr.includes('certificate invalid')) {
                return 'SSL证书无效，请检查证书配置';
            }

            if (errorStr.includes('certificate') || errorStr.includes('SSL') || errorStr.includes('TLS')) {
                return 'SSL/TLS连接错误，请检查网络连接和证书配置';
            }

            return null;
        }

        // 修改 request.onerror 处理
        request.onerror = () => {
            const sslError = getSSLErrorMessage(request.statusText);
            const message = sslError || '请求出错';
            console.log('请求出错', message);
            logger.error(message, {
                statusText: request.statusText,
                url,
                headers,
                body,
                params
            });

            callbackParams?.handleError?.({
                code: request.status,
                msg: message
            });
        };

        // 请求完成
        request.onload = () => {
            if (timeoutId) clearTimeout(timeoutId);

            const { status, readyState, responseType } = request;
            logger.debug('请求状态', { readyState, status });

            if (readyState === 4) {
                if (status >= 200 && status < 300) {
                    handleSuccessResponse(request, responseType, resolve, logger);
                } else {
                    // 统一错误回调结构；XHR 的错误体在 response/responseText
                    callbackParams?.handleError?.({
                        code: status,
                        msg: request.statusText || 'HTTP Error',
                        method: params.method,
                        url,
                        params: body,
                        headers,
                        error: (request.response ?? request.responseText ?? 'Unknown XHR error'),
                    });

                    handleErrorResponse(request, responseType, reject, logger, url, body, params);
                }
            }
        };

        // 设置超时时间
        if (typeof params.timeout === "number") {
            request.timeout = params.timeout;
        }

        logger.info('请求参数', params);

        // 发送请求
        request.send(body);
    });
}

function handleSuccessResponse<T>(
    request: XMLHttpRequest | any,       // XMLHttpRequest 对象
    responseType: string,         // 预期的响应类型
    resolve: (value: T) => void,  // Promise 的 resolve 回调
    logger: ILogger               // 日志记录器
) {
    // 记录请求成功日志
    logger.debug('请求成功', request);

    // 根据响应类型处理响应数据
    switch (responseType) {
        case RESPONSE_TYPE.Json:
            // 处理 JSON 响应
            const jsonResponse = request.response ?? request._response as T;
            resolve(jsonResponse ?? JSON.parse(request.responseText ?? request._responseText) as T);
            break;
        case RESPONSE_TYPE.Text:
            // 处理文本响应
            resolve(request.responseText as T);
            break;
        case RESPONSE_TYPE.Empty:
            // 处理空响应
            resolve(undefined as T);
            break;
    }
}

function handleErrorResponse<T>(
    request: XMLHttpRequest,
    responseType: string,
    reject: (reason?: any) => void,
    logger: ILogger,
    url: string,
    body: object | string | undefined,
    params: IParams
) {
    const error: any = ERROR;
    const status = request.status;
    const errorInfo = error[`err_${status}`];

    logger.error('请求失败', {
        error: errorInfo,
        status,
        url,
        body,
        params
    });

    switch (responseType) {
        case RESPONSE_TYPE.Json:
            const response = request.response ?? JSON.stringify(request.responseText);
            logger.error('响应内容', response);
            reject(response);
            break;
        case RESPONSE_TYPE.Text:
            logger.error('响应内容', request.responseText);
            reject(request.responseText);
            break;
        default:
            reject(errorInfo);
            break;
    }
}

export default sendXmlHttpRequest
